/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 ~ 2010 Patrick Huy <patrick.huy@frz.cc> 
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License version 3
as published by the Free Software Foundation. You may not use, modify
or distribute this program under any other version of the
GNU Affero General Public License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package tools;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * Provides a suite of utilities for manipulating strings.
 *
 * @author Frz
 * @version 1.0
 * @since Revision 336
 */
public class StringUtil {

  /**
   * Gets a string padded from the left to <code>length</code> by
   * <code>padchar</code>.
   *
   * @param in      The input string to be padded.
   * @param padchar The character to pad with.
   * @param length  The length to pad to.
   * @return The padded string.
   */
  public static final String getLeftPaddedStr(final String in, final char padchar, final int length) {
    StringBuilder builder = new StringBuilder(length);
    for (int x = in.length(); x < length; x++) {
      builder.append(padchar);
    }
    builder.append(in);
    return builder.toString();
  }

  /**
   * Gets a string padded from the right to <code>length</code> by
   * <code>padchar</code>.
   *
   * @param in      The input string to be padded.
   * @param padchar The character to pad with.
   * @param length  The length to pad to.
   * @return The padded string.
   */
  public static final String getRightPaddedStr(final String in, final char padchar, final int length) {
    StringBuilder builder = new StringBuilder(in);
    for (int x = in.length(); x < length; x++) {
      builder.append(padchar);
    }
    return builder.toString();
  }

  /**
   * Joins an array of strings starting from string <code>start</code> with
   * a space.
   *
   * @param arr   The array of strings to join.
   * @param start Starting from which string.
   * @return The joined strings.
   */
  public static final String joinStringFrom(final String arr[], final int start) {
    return joinStringFrom(arr, start, " ");
  }

  /**
   * Joins an array of strings starting from string <code>start</code> with
   * <code>sep</code> as a seperator.
   *
   * @param arr   The array of strings to join.
   * @param start Starting from which string.
   * @return The joined strings.
   */
  public static final String joinStringFrom(final String arr[], final int start, final String sep) {
    StringBuilder builder = new StringBuilder();
    for (int i = start; i < arr.length; i++) {
      builder.append(arr[i]);
      if (i != arr.length - 1) {
        builder.append(sep);
      }
    }
    return builder.toString();
  }

  /**
   * Makes an enum name human readable (fixes spaces, capitalization, etc)
   *
   * @param enumName The name of the enum to neaten up.
   * @return The human-readable enum name.
   */
  public static final String makeEnumHumanReadable(final String enumName) {
    StringBuilder builder = new StringBuilder(enumName.length() + 1);
    for (String word : enumName.split("_")) {
      if (word.length() <= 2) {
        builder.append(word); // assume that it's an abbrevation
      } else {
        builder.append(word.charAt(0));
        builder.append(word.substring(1).toLowerCase());
      }
      builder.append(' ');
    }
    return builder.substring(0, enumName.length());
  }

  /**
   * Counts the number of <code>chr</code>'s in <code>str</code>.
   *
   * @param str The string to check for instances of <code>chr</code>.
   * @param chr The character to check for.
   * @return The number of times <code>chr</code> occurs in <code>str</code>.
   */
  public static final int countCharacters(final String str, final char chr) {
    int ret = 0;
    for (int i = 0; i < str.length(); i++) {
      if (str.charAt(i) == chr) {
        ret++;
      }
    }
    return ret;
  }

  public static final String getReadableMillis(long startMillis, long endMillis) {
    StringBuilder sb = new StringBuilder();
    double elapsedSeconds = (endMillis - startMillis) / 1000.0;
    int elapsedSecs = ((int) elapsedSeconds) % 60;
    int elapsedMinutes = (int) (elapsedSeconds / 60.0);
    int elapsedMins = elapsedMinutes % 60;
    int elapsedHrs = elapsedMinutes / 60;
    int elapsedHours = elapsedHrs % 24;
    int elapsedDays = elapsedHrs / 24;
    if (elapsedDays > 0) {
      boolean mins = elapsedHours > 0;
      sb.append(elapsedDays);
      sb.append(" day" + (elapsedDays > 1 ? "s" : "") + (mins ? ", " : "."));
      if (mins) {
        boolean secs = elapsedMins > 0;
        if (!secs) {
          sb.append("and ");
        }
        sb.append(elapsedHours);
        sb.append(" hour" + (elapsedHours > 1 ? "s" : "") + (secs ? ", " : "."));
        if (secs) {
          boolean millis = elapsedSecs > 0;
          if (!millis) {
            sb.append("and ");
          }
          sb.append(elapsedMins);
          sb.append(" minute" + (elapsedMins > 1 ? "s" : "") + (millis ? ", " : "."));
          if (millis) {
            sb.append("and ");
            sb.append(elapsedSecs);
            sb.append(" second" + (elapsedSecs > 1 ? "s" : "") + ".");
          }
        }
      }
    } else if (elapsedHours > 0) {
      boolean mins = elapsedMins > 0;
      sb.append(elapsedHours);
      sb.append(" hour" + (elapsedHours > 1 ? "s" : "") + (mins ? ", " : "."));
      if (mins) {
        boolean secs = elapsedSecs > 0;
        if (!secs) {
          sb.append("and ");
        }
        sb.append(elapsedMins);
        sb.append(" minute" + (elapsedMins > 1 ? "s" : "") + (secs ? ", " : "."));
        if (secs) {
          sb.append("and ");
          sb.append(elapsedSecs);
          sb.append(" second" + (elapsedSecs > 1 ? "s" : "") + ".");
        }
      }
    } else if (elapsedMinutes > 0) {
      boolean secs = elapsedSecs > 0;
      sb.append(elapsedMinutes);
      sb.append(" minute" + (elapsedMinutes > 1 ? "s" : "") + (secs ? " " : "."));
      if (secs) {
        sb.append("and ");
        sb.append(elapsedSecs);
        sb.append(" second" + (elapsedSecs > 1 ? "s" : "") + ".");
      }
    } else if (elapsedSeconds > 0) {
      sb.append((int) elapsedSeconds);
      sb.append(" second" + (elapsedSeconds > 1 ? "s" : "") + ".");
    } else {
      sb.append("None.");
    }
    return sb.toString();
  }

  public static final int Solve(final String function, final int level) {
    if (function.equals("")) {
      return Integer.valueOf(function);
    }
    String formula = function;
    formula = formula.replace("u", "ceil");
    formula = formula.replace("d", "floor");
    //formula = formula.replace("=", "");
    MathEvaluator m = new MathEvaluator(formula);
    m.addVariable("x", level);

    return m.getValue().intValue();
  }

  public static String readFileAsString(String path) {
    StringBuilder builder = new StringBuilder();
    try {
      for (String str : Files.readAllLines(Paths.get(path))) {
        builder.append(str + System.lineSeparator());
      }
      return builder.toString();
    } catch (IOException e) {
      System.out.println("Error while loading file " + path + " " + e.getMessage());
    }
    return "";
  }
}
